package cn.ecut.dzy.lock;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @program: java-interview
 * @description: 循环比较获取直到成功为止，没有类似于wait的阻塞  *  *
 * 通过CAS操作完成自旋锁，A线程先进来调用myLock方法自己持有锁5秒，
 * B随后进来发现当前有线程持有锁，不是null，所以只能通过自旋等待，直到A释放锁后B随后抢到
 * @author: DingZhenYun
 * @create: 2021-10-24 15:51
 **/

public class SpinLockDemo {
    // 现在的泛型装的是Thread，原子引用线程
    AtomicReference<Thread> atomicReference = new AtomicReference<>();

    public void myLock() {
        // 获取当前进来的线程
        Thread thread = Thread.currentThread();
        System.out.println(Thread.currentThread().getName() + "\t come in ");
        do{
            System.out.println(Thread.currentThread().getName() + "\t 时候cas ");

            // 开始自旋，期望值是null，更新值是当前线程，如果是null，则更新为当前线程，否者自旋
        }while (!atomicReference.compareAndSet(null,thread));
    }
    public void myUnLock() {
        // 获取当前进来的线程
        Thread thread = Thread.currentThread();
        System.out.println(Thread.currentThread().getName() + "\t invoked myUnlock() ");
        atomicReference.compareAndSet(thread,null);

    }
    public static void main(String[] args) {
        SpinLockDemo spinLockDemo=new SpinLockDemo();
        // 启动t1线程，开始操作
        new Thread(() -> {

            // 开始占有锁
            spinLockDemo.myLock();

            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            // 开始释放锁
            spinLockDemo.myUnLock();

        }, "t1").start();


        // 让main线程暂停1秒，使得t1线程，先执行
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 1秒后，启动t2线程，开始占用这个锁
        new Thread(() -> {

            // 开始占有锁
            spinLockDemo.myLock();
            // 开始释放锁
            spinLockDemo.myUnLock();

        }, "t2").start();
    }
}
